package com.qyhl.school.school.vlog.shoot;

import android.annotation.SuppressLint;
import android.graphics.Bitmap;
import android.graphics.ImageFormat;
import android.hardware.Camera;
import android.media.MediaMetadataRetriever;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.Environment;
import android.util.Log;
import android.view.OrientationEventListener;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

import com.alibaba.android.arouter.facade.annotation.Route;
import com.alibaba.android.arouter.launcher.ARouter;
import com.luck.picture.lib.samsung.DeviceUtils;
import com.luck.picture.lib.samsung.SamSungVideo;
import com.makeramen.roundedimageview.RoundedImageView;
import com.qyhl.school.R;
import com.qyhl.school.R2;
import com.qyhl.webtv.commonlib.constant.ARouterPathConstant;
import com.qyhl.webtv.commonlib.constant.ChannelConfigConstant;
import com.qyhl.webtv.commonlib.constant.PathConfigConstant;
import com.qyhl.webtv.module_microvideo.shortvideo.shoot.ShortVideoShoot2Activity;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.UUID;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;

@Route(path = ARouterPathConstant.SCHOOL_SHOOT2)
public class SchoolShoot2Activity extends AppCompatActivity implements SurfaceHolder.Callback, MediaRecorder.OnErrorListener {
    @BindView(R2.id.progress_bar)
    ProgressBar progressBar;
    @BindView(R2.id.shoot_btn)
    RoundedImageView shootBtn;
    @BindView(R2.id.shoot_tips)
    TextView shootTips;
    @BindView(R2.id.shoot_local)
    TextView shootLocal;
    @BindView(R2.id.shoot_cancel)
    ImageView shootCancel;
    @BindView(R2.id.shoot_next)
    ImageView shootNext;
    @BindView(R2.id.camera_switch)
    ImageView cameraSwitch;
    @BindView(R2.id.surface_view)
    SurfaceView mSurfaceView;

    private static final String TAG = "SchoolShoot2";
    /**
     * 录制器
     */
    private MediaRecorder mMediaRecorder;


    private String mVideoCoverPath;

    //视频录制文件夹
    private final String SAVE_VIDOE_PATH = Environment.getExternalStorageDirectory().getPath() + File.separator + ChannelConfigConstant.UMENG_CHANNEL_ID + File.separator + "video";

    private String pathName;

    /**
     * 视频选择
     */
    public static final int CHOOSE_VIDEO = 155;

    private CountDownTimer mCountDownTimer;//计时器

    /**
     * 动画
     */
    Animation mAnimation = null;

    private int curTime = 0;

    //最大录制时长
    private static final long MAX_RECORD_TIME = 180000;//ms


    private VideoStatus videoStatus = VideoStatus.PREPAREING;

    private SurfaceHolder mSurfaceHolder;

    private int tagId;

    @Override
    public void onError(MediaRecorder mr, int what, int extra) {
        try {
            if (mr != null)
                mr.reset();
            showStartLayout();
            Log.e("@@@@", "what:" + what + " extra:" + extra);
            Toast.makeText(this, "视频录制出错,请重试", Toast.LENGTH_SHORT).show();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }


    /**
     * 闪光灯类型枚举 默认为关闭
     */
    public enum FlashMode {
        /**
         * ON:拍照时打开闪光灯
         */
        ON,
        /**
         * OFF：不打开闪光灯
         */
        OFF,
        /**
         * AUTO：系统决定是否打开闪光灯
         */
        AUTO,
        /**
         * TORCH：一直打开闪光灯
         */
        TORCH
    }

    private int mWidthPixel, mHeightPixel;//SurfaceView的宽高
    private int mCurrCameraFacing = 0;//当前设置头类型,0:后置/1:前置
    private Camera.Parameters mCaptureParameters;//相机配置，在录像前记录，用以录像结束后恢复原配置
    private ShortVideoShoot2Activity.FlashMode mFlashMode = ShortVideoShoot2Activity.FlashMode.AUTO;//闪光灯模式
    private int mOrientation;//当前屏幕旋转角度
    private Camera mCamera;

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        try {
            if (mCamera == null) {
                openCamera();
            }
            if (null != mCamera) {
                mCamera.setPreviewDisplay(mSurfaceHolder);
                mCamera.startPreview();
            }
        } catch (Exception e) {
            e.printStackTrace();
            Toast.makeText(this, "打开相机失败", Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        mWidthPixel = width;
        mHeightPixel = height;
        try {
            setCameraParameters();
        } catch (Exception e) {
            Log.e(TAG, e.toString() + "");
        }
        updateCameraOrientation();
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        releaseCamera();
    }

    /**
     * 打开相机
     */
    private void openCamera() {
        if (null != mCamera) {
            releaseCamera();
        }
        try {
            if (!checkCameraFacing(0) && !checkCameraFacing(1)) {
                Toast.makeText(this, "未发现有可用摄像头", Toast.LENGTH_SHORT).show();
                return;
            }
            if (!checkCameraFacing(mCurrCameraFacing)) {
                Toast.makeText(this, mCurrCameraFacing == 0 ? "后置摄像头不可用" : "前置摄像头不可用", Toast.LENGTH_SHORT).show();
                return;
            }
            mCamera = Camera.open(mCurrCameraFacing);
        } catch (Exception e) {
            e.printStackTrace();
            releaseCamera();
        }
    }

    /**
     * 设置相机参数
     */
    private void setCameraParameters() throws RuntimeException {
        if (null != mCamera) {
            Camera.Parameters params = mCamera.getParameters();
            Camera.Size preViewSize = getOptimalSize(params.getSupportedPreviewSizes(), mWidthPixel, mHeightPixel);
            if (null != preViewSize) {
                Log.e(TAG, "preViewSize:" + preViewSize.width + " : " + preViewSize.height);
                params.setPreviewSize(preViewSize.width, preViewSize.height);
            }

            Camera.Size pictureSize = getOptimalSize(params.getSupportedPictureSizes(), mWidthPixel, mHeightPixel);
            if (null != pictureSize) {
                Log.e(TAG, "pictureSize:" + pictureSize.width + " : " + pictureSize.height);
                params.setPictureSize(pictureSize.width, pictureSize.height);
            }
            //设置图片格式
            params.setPictureFormat(ImageFormat.JPEG);
            params.setJpegQuality(100);
            params.setJpegThumbnailQuality(100);

            List<String> modes = params.getSupportedFocusModes();
            if (modes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
                //支持自动聚焦模式
                params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
            }
            //设置闪光灯模式
            setFlashMode(mFlashMode);
            mCamera.setParameters(params);
            //开启屏幕朝向监听
            startOrientationChangeListener();
        }

    }

    /**
     * 初始化摄像
     */
    private void initRecord() {
        try {
            if (mMediaRecorder == null)
                mMediaRecorder = new MediaRecorder();
            else
                mMediaRecorder.reset();
            mCaptureParameters = mCamera.getParameters();
            setFlashMode(ShortVideoShoot2Activity.FlashMode.OFF);
            mCamera.unlock();
            mMediaRecorder.setCamera(mCamera);
            mMediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
            mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);//视频源
            mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);//音频源
            mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);//视频输出格式
            mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);//音频格式
            mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);//视频录制格式

            mMediaRecorder.setVideoSize(640, 480);//设置分辨率,640, 480像素
            //mMediaRecorder.setVideoFrameRate(17);// 设置每秒帧数 这个设置三星手机会出问题
            mMediaRecorder.setVideoEncodingBitRate(1024 * 1024);//清晰度
            mMediaRecorder.setOrientationHint(90);//输出旋转90度，保持竖屏录制

            mMediaRecorder.setOutputFile(getVideoFilePath(SAVE_VIDOE_PATH, ".mp4"));
            mMediaRecorder.prepare();
            mMediaRecorder.setOnErrorListener(this);
        } catch (Exception e) {
            e.printStackTrace();
            releaseCamera();
        }
    }

    /**
     * 设置闪关灯模式
     *
     * @param flashMode
     */
    public void setFlashMode(ShortVideoShoot2Activity.FlashMode flashMode) {
        if (mCamera != null && null != mCamera.getParameters()) {
            mFlashMode = flashMode;
            Camera.Parameters parameters = mCamera.getParameters();
            switch (flashMode) {
                case ON:
                    parameters.setFlashMode(Camera.Parameters.FLASH_MODE_ON);
                    break;
                case AUTO:
                    parameters.setFlashMode(Camera.Parameters.FLASH_MODE_AUTO);
                    break;
                case TORCH:
                    parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
                    break;
                default:
                    parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
                    break;
            }
            mCamera.setParameters(parameters);
        }
    }

    public ShortVideoShoot2Activity.FlashMode getFlashMode() {
        return mFlashMode;
    }

    /**
     * 切换闪关灯
     *
     * @return 返回当前闪关灯状态
     */
    public ShortVideoShoot2Activity.FlashMode switchFlashMode() {
        if (getFlashMode() == ShortVideoShoot2Activity.FlashMode.ON) {
            setFlashMode(ShortVideoShoot2Activity.FlashMode.OFF);
            return ShortVideoShoot2Activity.FlashMode.OFF;
        } else if (getFlashMode() == ShortVideoShoot2Activity.FlashMode.OFF) {
            setFlashMode(ShortVideoShoot2Activity.FlashMode.AUTO);
            return ShortVideoShoot2Activity.FlashMode.AUTO;
        } else if (getFlashMode() == ShortVideoShoot2Activity.FlashMode.AUTO) {
            setFlashMode(ShortVideoShoot2Activity.FlashMode.TORCH);
            return ShortVideoShoot2Activity.FlashMode.TORCH;
        } else if (getFlashMode() == ShortVideoShoot2Activity.FlashMode.TORCH) {
            setFlashMode(ShortVideoShoot2Activity.FlashMode.ON);
            return ShortVideoShoot2Activity.FlashMode.ON;
        }
        return null;
    }

    /**
     * 启动屏幕朝向改变监听函数 用于在屏幕横竖屏切换时改变保存的图片的方向
     */
    private void startOrientationChangeListener() {
        OrientationEventListener orientationEventListener = new OrientationEventListener(this) {
            @Override
            public void onOrientationChanged(int rotation) {

                if ((rotation >= 0 && rotation <= 45) || rotation > 315) {
                    rotation = 0;
                } else if (rotation > 45 && rotation <= 135) {
                    rotation = 90;
                } else if (rotation > 135 && rotation <= 225) {
                    rotation = 180;
                } else if (rotation > 225 && rotation <= 315) {
                    rotation = 270;
                } else {
                    rotation = 0;
                }
                if (rotation == mOrientation) return;
                mOrientation = rotation;
                updateCameraOrientation();
            }
        };
        orientationEventListener.enable();
    }

    /**
     * 根据当前朝向修改保存图片的旋转角度
     */
    private void updateCameraOrientation() {
        try {
            if (mCamera != null && null != mCamera.getParameters()) {
                Camera.Parameters parameters = mCamera.getParameters();
                //rotation参数为 0、90、180、270。水平方向为0。
                int rotation = 90 + mOrientation == 360 ? 0 : 90 + mOrientation;
                //前置摄像头需要对垂直方向做变换，否则照片是颠倒的
                if (mCurrCameraFacing == 1) {
                    if (rotation == 90) rotation = 270;
                    else if (rotation == 270) rotation = 90;
                }
                parameters.setRotation(rotation);//生成的图片转90°
                //预览图片旋转90°
                mCamera.setDisplayOrientation(90);//预览转90°
                mCamera.setParameters(parameters);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 检查是否有摄像头
     *
     * @param facing 前置还是后置
     * @return
     */
    private boolean checkCameraFacing(int facing) {
        int cameraCount = Camera.getNumberOfCameras();
        Camera.CameraInfo info = new Camera.CameraInfo();
        for (int i = 0; i < cameraCount; i++) {
            Camera.getCameraInfo(i, info);
            if (facing == info.facing) {
                return true;
            }
        }
        return false;
    }

    /**
     * 切换摄像头
     */
    public void switchCamera() {
        if (mCurrCameraFacing == 0) {
            mCurrCameraFacing = Camera.CameraInfo.CAMERA_FACING_FRONT;
        } else {
            mCurrCameraFacing = Camera.CameraInfo.CAMERA_FACING_BACK;
        }
        if (null != mMediaRecorder && videoStatus == VideoStatus.WORKING) stopRecordingVideo();

        openCamera();
        if (mCamera != null) {
            try {
                setCameraParameters();
            } catch (Exception e) {
                Log.e(TAG, e.toString() + "");
            }
            updateCameraOrientation();
            try {
                mCamera.setPreviewDisplay(mSurfaceHolder);
                mCamera.startPreview();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }


    private enum VideoStatus {
        PREPAREING,
        WORKING,
        COMPLETE
    }


    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);//不显示标题栏
        setContentView(R.layout.micro_activity_short_video_shoot2);
        ButterKnife.bind(this);
        tagId = getIntent().getIntExtra("tagId", 0);
        //全屏显示
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
        initView();
    }

    /**
     * 获取最优尺寸
     *
     * @param sizes
     * @param w
     * @param h
     * @return
     */
    private Camera.Size getOptimalSize(List<Camera.Size> sizes, int w, int h) {
        final double ASPECT_TOLERANCE = 0.1;
        double targetRatio = (double) h / w;
        if (w > h)
            targetRatio = (double) w / h;
        if (sizes == null)
            return null;
        Camera.Size optimalSize = null;
        double minDiff = Double.MAX_VALUE;
        int targetHeight = h;
        for (Camera.Size size : sizes) {
            double ratio = (double) size.width / size.height;
            if (size.height >= size.width)
                ratio = (float) size.height / size.width;
            if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE)
                continue;
            if (Math.abs(size.height - targetHeight) < minDiff) {
                optimalSize = size;
                minDiff = Math.abs(size.height - targetHeight);
            }
        }
        if (optimalSize == null) {
            minDiff = Double.MAX_VALUE;
            for (Camera.Size size : sizes) {
                if (Math.abs(size.height - targetHeight) < minDiff) {
                    optimalSize = size;
                    minDiff = Math.abs(size.height - targetHeight);
                }
                Log.d(TAG, "getOptimalSize: width:" + size.width + " height:" + size.height + " minDiff:" + minDiff);
            }
        }

        return optimalSize;
    }


    private void initView() {
        mSurfaceHolder = mSurfaceView.getHolder();
        mSurfaceHolder.addCallback(this);
        showStartLayout();
        mAnimation = AnimationUtils.loadAnimation(this, R.anim.micro_short_video_shoot_btn_scale);

    }

    private void showStartLayout() {
        shootNext.setVisibility(View.GONE);
        shootCancel.setVisibility(View.GONE);
        shootLocal.setVisibility(View.VISIBLE);
        cameraSwitch.setVisibility(View.VISIBLE);
        curTime = 0;
        progressBar.setProgress(curTime);
        shootTips.setText("拍摄视频");
        shootBtn.setImageResource(R.color.white);
        videoStatus = VideoStatus.PREPAREING;
    }


    @SuppressLint("SetTextI18n")
    private void showCompleteLayout(int endTime) {
        shootNext.setVisibility(View.VISIBLE);
        shootCancel.setVisibility(View.VISIBLE);
        shootLocal.setVisibility(View.GONE);
        shootTips.setText(endTime + "s");
        shootBtn.setImageResource(R.color.white);
        videoStatus = VideoStatus.COMPLETE;
        endConfigure();
    }

    @SuppressLint("SetTextI18n")
    private void startConfigure() {
        videoStatus = VideoStatus.WORKING;
        shootLocal.setVisibility(View.GONE);
        cameraSwitch.setVisibility(View.GONE);
        shootTips.setText("0s");
        countDownTime();
        startRecordingVideo();
        shootBtn.setImageResource(R.color.micro_short_video_blue);
        shootBtn.startAnimation(mAnimation);
    }

    private void endConfigure() {
        shootBtn.setAnimation(null);
        shootBtn.clearAnimation();
        if (mCountDownTimer != null) {
            mCountDownTimer.cancel();
        }
        getPicture(pathName);
    }


    private void startRecordingVideo() {
        if (mCamera == null)
            openCamera();
        if (mCamera == null) {
            return;
        }
//        mCamera.autoFocus(null);
        initRecord();
        if (null != mMediaRecorder) {
            try {
                mMediaRecorder.start();//开始录制
            } catch (Exception e) {
                Log.e("@@@@", e.toString());
            }

        }
    }

    @SuppressLint("NewApi")
    private void stopRecordingVideo() {
        // Stop recording
        try {
            if (videoStatus == VideoStatus.WORKING) mMediaRecorder.stop();
            mMediaRecorder.reset();
            mMediaRecorder.release();
            mMediaRecorder = null;
            if (DeviceUtils.isSamsung()) {
                String name = SAVE_VIDOE_PATH + File.separator + "qz" + (System.currentTimeMillis() + 1) + ".mp4";
                SamSungVideo samSungVideo = new SamSungVideo(pathName, name);
                samSungVideo.muxerMedia();
                pathName = name;
            }

            //恢复相机参数
            if (mCaptureParameters != null && mCamera != null) {
                //重新连接相机
                mCamera.reconnect();
                //停止预览，注意这里必须先调用停止预览再设置参数才有效
                mCamera.stopPreview();
                //设置参数为录像前的参数，不然如果录像是低配，结束录制后预览效果还是低配画面
                mCamera.setParameters(mCaptureParameters);
                //重新打开
                mCamera.startPreview();
                mCaptureParameters = null;
            }
        } catch (Exception e) {
            Log.e("error_shoot", e.getMessage() == null ? "null" : e.getMessage());
            Toast.makeText(SchoolShoot2Activity.this,"录制时间过短",Toast.LENGTH_SHORT).show();
            showStartLayout();
            deleteFile();
        }
    }

    /**
     * 释放相机资源
     */
    private void releaseCamera() {
        if (null != mCamera) {
            try {
                mCamera.stopPreview();
                mCamera.release();
                mCamera = null;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }


    /**
     * 倒计时
     */
    private void countDownTime() {
        mCountDownTimer = new CountDownTimer(MAX_RECORD_TIME, 1000) {
            @SuppressLint("SetTextI18n")
            @Override
            public void onTick(long millisUntilFinished) {
                curTime += 1000;
                progressBar.setProgress(curTime / 100);
                Log.d("progressBar:", curTime / 100 + "");
                if (curTime % 1000 == 0) {
                    shootTips.setText(curTime / 1000 + "s");
                }
            }

            @Override
            public void onFinish() {
                progressBar.setProgress(18000);
                stopRecordingVideo();
                showCompleteLayout((int) (MAX_RECORD_TIME / 1000));

            }
        }.start();
    }

    @OnClick({R2.id.close_btn, R2.id.camera_switch, R2.id.shoot_layout, R2.id.shoot_cancel, R2.id.shoot_next})
    public void onViewClicked(View view) {
        int id = view.getId();
        if (id == R.id.close_btn) {
            finish();
        } else if (id == R.id.camera_switch) {
            switchCamera();
        } else if (id == R.id.shoot_layout) {
            switch (videoStatus) {
                case PREPAREING:
                    startConfigure();
                    break;
                case WORKING:
                    stopRecordingVideo();
                    showCompleteLayout(curTime / 1000);
                    break;
                case COMPLETE:
                    break;
            }
        } else if (id == R.id.shoot_cancel) {
            videoStatus = VideoStatus.PREPAREING;
            deleteFile();
            showStartLayout();
            mCamera.startPreview();
        } else if (id == R.id.shoot_next) {
            ARouter.getInstance()
                    .build(ARouterPathConstant.SCHOOL_VLOG_UPLOAD)
                    .withString("cover",mVideoCoverPath)
                    .withString("video",pathName)
                    .withInt("tagId",tagId)
                    .navigation();
            finish();
        }
    }


    /**
     * 获取文件路径
     *
     * @return
     */
    private String getVideoFilePath(String path, String suffix) {
        File file = new File(path);
        if (!file.exists()) {
            file.mkdirs();
        }
        pathName = path + File.separator + "qz" + System.currentTimeMillis() + suffix;
        return pathName;
    }

    /**
     * 删除文件
     */
    private void deleteFile() {
        if (pathName != null) {
            File file = new File(pathName);
            if (file.exists() && file.isFile()) {
                file.delete();
            }
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        releaseCamera();
    }

    @Override
    protected void onResume() {
        super.onResume();
        openCamera();
        mCamera.startPreview();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        releaseCamera();
        if (mMediaRecorder != null) {
            mMediaRecorder.release();
            mMediaRecorder = null;
        }
    }


    /**
     * 获取视频封面图
     */
    public void getPicture(String path) {
        File file = new File(path);
        //判断对象是否存在，不存在的话给出Toast提示
        if (file.exists()) {
            //提供统一的接口用于从一个输入媒体中取得帧和元数据
            MediaMetadataRetriever retriever = new MediaMetadataRetriever();
            retriever.setDataSource(path);
            Bitmap bitmap = retriever.getFrameAtTime();
            String dirpath = Environment.getExternalStorageDirectory().getPath() + PathConfigConstant.Pic;
            File dir = new File(dirpath);
            if (!dir.exists()) {
                dir.mkdirs();
            }
            String name = UUID.randomUUID().toString() + ".png";
            mVideoCoverPath = Environment.getExternalStorageDirectory().getPath() + PathConfigConstant.Pic + File.separator + name;
            FileOutputStream fos = null;
            try {
                fos = new FileOutputStream(mVideoCoverPath);
                bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
                fos.close();
            } catch (Exception e) {
                e.printStackTrace();
                Toast.makeText(SchoolShoot2Activity.this,"生成封面图失败",Toast.LENGTH_SHORT).show();
            }
        } else {
            Toast.makeText(SchoolShoot2Activity.this,"视频路径不存在",Toast.LENGTH_SHORT).show();
        }
    }

}
